cyklus While a Application.ProcessMessages, StringGrid

Otázka od: Petr Hložek

25. 9. 2002 7:32

Dobry den,

pisete ze pouziti Application.ProcessMessages v cyklu neni spravne.
mam cyklus napr:

while not Table1.eof do begin
   ....
   .... { Neco s tabulkou delam}
   Table1.Next;
   Application.ProcessMessages
end;

Ted kdyz se prepnu na jinou ulohu a zpet, okno se nevykresli a zustane bile.
K prekresleni dojde az po ukonceni cyklu. Toto vse se deje bez radku
Application.ProcessMessages. S Application.ProcessMessages to chodi jak ma.
Jak to tedy jinak vyresit?

Omlouvam se, mozna je to hloupy dotaz, ale povazuju se za zacatecnika a chci
se neco naucit.


Nevite prosim nekdo o komponente, ktera by byla potomkem StringGridu a umela
slouceni bunek?


Dekuji.

Petr

Odpovedá: Jan Sebelík

25. 9. 2002 11:30

> Odesílatel: Petr Hložek <petr_h@mrp.cz>
> pisete ze pouziti Application.ProcessMessages v cyklu neni spravne.
Myslim, ze to tak nebylo mysleno.
Application.ProcessMessages je OK.
Pokud jsem si vsiml, tak to bylo kritizovano pouze v souvislosti s technikami
pro koordinaci threadu.

Honza
=========================================
= HAES - RNDr. Jan Sebelik
= http://www.haes.cz
= Skolici a konzultacni stredisko pro Delphi a Win32
= Vojtiskova 206
= 507 81 Lazne Belohrad
= tel. 493 792 931 (mobil 776 347735)
=========================================

Odpovedá: Peter Vlkovic

25. 9. 2002 11:56

Ahoj,

pouzitie Application.ProcessMessages prinasa zo sebou pomerne
velku reziu s obsluhou sprav v ramci aplikacie, co sa moze
v niektorych sluckach s vysokym poctom iteracii prejavit
vyraznym spomalenim behu aplikacie v danej slucke.
Priebeh takychto sluciek vsak pomerne casto treba vyobrazit
aj vizualne prostrednictvom nejakeho pocitadla, alebo
progressbaru a pod. V casovo kratsich pasazach staci zavolat
metodu Update() prislusneho control prvku, ktorym zobrazujeme
priebeh. V pripade casovo narocnejsich sluciek je vhodne pocet
volani Application.ProcessMessages obmedzit, napriklad zavolat
tuto metodu len po urcitom pocte vykonanych iteracii.
V niektorych programoch som obsluhu sprav riesil pomocou
pomocneho pocitadla uplynuteho casu, ktory zistujem
funkciou GetTickCount nasledovne:

var
  OldTicks, CurrentTicks: DWord;

// nasledovna konstanta udava, v akych casovych
// intervaloch sa vykonava ProcessMessages
// (konstanta je v nasobkoch milisekund)
const
  HandlingMessagesDelay = 100;


pred spustenim slucky treba inicializovat OldTicks:

  OldTicks := GetTickCount();

V slucke potom testujem uplynutie stanoveneho
poctu "TickCounts" nasledovne:

   CurrentTicks := GetTickCount();
   if OldTicks + HandlingMessagesDelay < CurrentTicks then
      begin
      Application.ProcessMessages();
      OldTicks := CurrentTicks;
      end;


Vlkovic



> pisete ze pouziti Application.ProcessMessages v cyklu neni spravne.
> mam cyklus napr:
>
> while not Table1.eof do begin
> ....
> .... { Neco s tabulkou delam}
> Table1.Next;
> Application.ProcessMessages
> end;

Odpovedá: Rumcajs - konference

25. 9. 2002 14:09

AdvStringGrid - rano semto tu psal
Rumcajs
>
> Nevite prosim nekdo o komponente, ktera by byla potomkem StringGridu a
umela
> slouceni bunek?
>
>
> Dekuji.
>
> Petr
>
>


---
Odchozí zpráva neobsahuje viry.
Zkontrolováno antivirovým systémem AVG (http://www.grisoft.cz).
Verze: 6.0.389 / Virová báze: 220 - datum vydání: 16.9.2002

Odpovedá: Martin Schayna

25. 9. 2002 15:51

----- Original Message -----
From: "Petr Hložek" <petr_h@mrp.cz>
> pisete ze pouziti Application.ProcessMessages v cyklu neni spravne.
> mam cyklus napr:
>
> while not Table1.eof do begin
> ....
> .... { Neco s tabulkou delam}
> Table1.Next;
> Application.ProcessMessages
> end;
>
> Ted kdyz se prepnu na jinou ulohu a zpet, okno se nevykresli a zustane bile.
> K prekresleni dojde az po ukonceni cyklu. Toto vse se deje bez radku
> Application.ProcessMessages. S Application.ProcessMessages to chodi jak ma.
> Jak to tedy jinak vyresit?

Pokud napr. stiskem tlacitka na formulari vyvolas v OnClick dele trvajici
akci, ve ktere budes pravidelne volat Application.ProcessMessages,
bude tvoje okno zpracovavat zpravy -- tj. bude se prekreslovat ale
zaroven (coz je mnohem horsi) budou reagovat i ovladaci prvky tveho
okna, takze uzivatel bude moci stisknout to tlacitko podruhe!!!
Takze behem vyvolani ProcessMessages se znovu vyvola OnClick.
Co to zpusobi za zmatek ti urcite dochazi.

Lze to resit tak ze se behem dele trvajici akce ktera bude ProcessMessages
vyvolavat vsechny ovladaci prvky disabluji.

Delal jsem prevod dat ktery bezel u klientu mnoho hodin. Tam by
se teoreticky nemusel ProcessMessages volat, ale pak nesel prevod
uzivatelsky pozastavit ale ani uspat pocitac (je zajimave ze k uspani
pocitace musi procesy odevzdavat cas, kde je ten proklamovany
preemptivni multitasking  
Aby to fungovalo, musel jsem ProcessMessages volat a disablovat
vsechny ovladaci prvky krome jednoho tlacitka pro uzivatelske
preruseni, pak StandBy a Hibernate opravdu zabral.

Martin Schayna

Odpovedá: Petr Vones

25. 9. 2002 14:27

From: "Martin Schayna" <mschayna@aktis.cz>
> akci, ve ktere budes pravidelne volat Application.ProcessMessages,
> bude tvoje okno zpracovavat zpravy -- tj. bude se prekreslovat ale
> zaroven (coz je mnohem horsi) budou reagovat i ovladaci prvky tveho
> okna, takze uzivatel bude moci stisknout to tlacitko podruhe!!!
> Takze behem vyvolani ProcessMessages se znovu vyvola OnClick.
> Co to zpusobi za zmatek ti urcite dochazi.

Spravne, navic se ta funkce zavola zevnitr te smycky, takze nejen ze se zavola
znovu ale i ve zcela jine situaci.

> Lze to resit tak ze se behem dele trvajici akce ktera bude ProcessMessages
> vyvolavat vsechny ovladaci prvky disabluji.

To je jen pokus o obchazeni dusledku bez reseni priciny (ackoli pomoci akci by
to slo resit jeste relativne prehledne). Jedna moznost je pro prekresleni
volat cas od casu metodu Update, ale lepsi je presunout tuto dlouhotrvajici
cinnost do samostatneho threadu a hlavni thread nechat ciste jen pro ovladani
aplikace a GUI.

Petr Vones

Odpovedá: Jiri Foldyna

25. 9. 2002 17:39

> pisete ze pouziti Application.ProcessMessages v cyklu neni spravne.
> mam cyklus napr:
>
> while not Table1.eof do begin
> ....
> .... { Neco s tabulkou delam}
> Table1.Next;
> Application.ProcessMessages
> end;
>
> Ted kdyz se prepnu na jinou ulohu a zpet, okno se nevykresli
> a zustane bile.
> K prekresleni dojde az po ukonceni cyklu. Toto vse se deje bez radku
> Application.ProcessMessages. S Application.ProcessMessages to
> chodi jak ma.
> Jak to tedy jinak vyresit?

Ahoj,

nic neni ani cerne, ani bile. Application.ProcessMessages ma krome toho, ze
prekresli okno jeste dalsi dusledek, a to sice, ze se zpracuje udalost napr.
od tlacitka. To muze byt jak nevhodne (napr. dalsi spusteni tveho cyklu,
tentokrat zevnitr), tak vhodne - napr. pro realizaci uzivatelskeho preruseni
cyklu. Asi je treba zvazit, co potrebujes, a podle toho se zaridit.
Prekresleni okna zaridis treba pomoci Refresh, pro zablokovani udalosti od
kontrolu muzes pouzit OnUpdate z Action (pokud je nepouzivas, vrele
doporucuji), nebo muzes pouzit dalsi thread, proste variant je vice. Ja se
pouziti ProcessMessages nevyhybam, pokud potrebuji soubezne s
dlouhotrvajicim cyklem jeste zajistit rekaci na zasahy operatora, a nechci
pouzit dalsi thread.

Zdravim

Jiri Foldyna
mailto:jiri.f@avizo.cz

Odpovedá: Martin Schayna

25. 9. 2002 16:35

----- Original Message -----
From: "Petr Vones" <pvones@mbox.vol.cz>
> From: "Martin Schayna" <mschayna@aktis.cz>
> > Lze to resit tak ze se behem dele trvajici akce ktera bude ProcessMessages
> > vyvolavat vsechny ovladaci prvky disabluji.
>
> To je jen pokus o obchazeni dusledku bez reseni priciny (ackoli pomoci akci
by
> to slo resit jeste relativne prehledne). Jedna moznost je pro prekresleni
> volat cas od casu metodu Update, ale lepsi je presunout tuto dlouhotrvajici
> cinnost do samostatneho threadu a hlavni thread nechat ciste jen pro ovladani
> aplikace a GUI.

Thread je samozrejme nejlepsi reseni, ale je otazka jak se to zachova pri
pokusu uspat takto pracujici pocitac. Nechapu proc to nejde kdyz je
hlavni thread v dlouhotrvajici smycce.

A pozor, davkova aplikace podporujici StandBy a Hibernate neni
zadny akademicky zajimavy problemek, to je pozadavek z praxe
kdy se vysledek nekolikadeniho prevodu dat nemuze jen tak vyhodit
kvuli vypadku proudu!

Martin Schayna

Odpovedá: Petr Vones

25. 9. 2002 16:46

From: "Martin Schayna" <mschayna@aktis.cz>
> Thread je samozrejme nejlepsi reseni, ale je otazka jak se to zachova pri
> pokusu uspat takto pracujici pocitac. Nechapu proc to nejde kdyz je hlavni
> thread v dlouhotrvajici smycce.

S timhle jsme nikdy nic nedelal, ale nemuze na to mit vliv pouziti funkce
SetThreadExecutionState ?

Petr Vones

Odpovedá: Ondrej Kelle

25. 9. 2002 18:24

> Delal jsem prevod dat ktery bezel u klientu mnoho hodin. Tam by
> se teoreticky nemusel ProcessMessages volat, ale pak nesel prevod
> uzivatelsky pozastavit ale ani uspat pocitac (je zajimave ze k uspani
> pocitace musi procesy odevzdavat cas, kde je ten proklamovany
> preemptivni multitasking  
> Aby to fungovalo, musel jsem ProcessMessages volat a disablovat
> vsechny ovladaci prvky krome jednoho tlacitka pro uzivatelske
> preruseni, pak StandBy a Hibernate opravdu zabral.

Mam pocit, ze to nema s multitaskingom nic spolocne. Moja teoria (nemam to
odskusane) znie takto:
Windows pred prechodom do power management rezimu vysle kazdej aplikacii
spravu WM_POWERBROADCAST a tym jej dava sancu, aby tomuto prechodu zabranila
(vratenim hodnoty BROADCAST_QUERY_DENY).
Power management teda zrejme nefungoval, pretoze Tvoja aplikacia
nespracovavala ziadne spravy a tym padom ani WM_POWERBROADCAST.
Defaultne spravanie je zrejme nakodovane v DefWindowProc, takze aplikacia,
ktora tuto spravu explicitne neosetruje, prechod do power management rezimu
povoli. Musi ale spracovavat spravy.
Mozno sa mylim, ale takto mi to znie logicky.

TOndrej

Odpovedá: Martin Schayna

25. 9. 2002 16:12

----- Original Message -----
From: "Petr Vones" <pvones@mbox.vol.cz>
> From: "Martin Schayna" <mschayna@aktis.cz>
> > Thread je samozrejme nejlepsi reseni, ale je otazka jak se to zachova pri
> > pokusu uspat takto pracujici pocitac. Nechapu proc to nejde kdyz je hlavni
> > thread v dlouhotrvajici smycce.
>
> S timhle jsme nikdy nic nedelal, ale nemuze na to mit vliv pouziti funkce
> SetThreadExecutionState ?

Myslim ze ne, pomoci teto funkce se naopak rika systemu, ze thread pracuje
a proto se pocitac nesmi samovolne uspat. Ja potrebuji naopak docilit toho aby
pocitac sel uspat, treba nasilim (napr. Start->Shut down->Hibernate).
Pokud se behem prace pravidelne nevola Application.ProcessMessages,
uspat se ho nepodari. Od skutecneho mutlitaskingu bych ocekaval ze
zmrazit vsechny procesy/thready a hibernovat pujde v kazdy okamzik
a ne jen pokud spolupracuje aplikace.  

Martin Schayna

Odpovedá: Petr Vones

25. 9. 2002 19:12

From: "Martin Schayna" <mschayna@aktis.cz>
> pocitac sel uspat, treba nasilim (napr. Start->Shut down->Hibernate).
> Pokud se behem prace pravidelne nevola Application.ProcessMessages,
> uspat se ho nepodari. Od skutecneho mutlitaskingu bych ocekaval ze

Pak je to asi to co psal Ondrej Kelle, ze je system ceka na odpoved zpravy
WM_POWERBROADCAST. Na druhe strane pokud neodpovi do 20ti vterin tak by to mel
system povazovat za vyrizene a akci povolit, viz PBT_APMQUERYSUSPEND

Petr Vones

Odpovedá: Jan Sebelík

25. 9. 2002 18:47

Jak lze taky pouzit Application.ProcessMessages?

Pred casem jsem byl nucen psat vlastni tisk na TPrinter.
Po hroznem usili se to nejak podarilo.
Jenze to na nekterych typech tiskaren zatuhlo.
Zeptal jsem se Vaska Krmely (Sinea), zda by neco neporadil.

Odpoved:
Zavolej "ve vhodnem okamziku" asi tak 3-5 x Aplication.ProcessMessages.
Zacalo to fungovat  

Honza
=========================================
= HAES - RNDr. Jan Sebelik
= http://www.haes.cz
= Skolici a konzultacni stredisko pro Delphi a Win32
= Vojtiskova 206
= 507 81 Lazne Belohrad
= tel. 493 792 931 (mobil 776 347735)
=========================================

Odpovedá: Petr Vones

25. 9. 2002 21:23

From: "Jan Sebelík" <honza@haes.cz>
> Zavolej "ve vhodnem okamziku" asi tak 3-5 x Aplication.ProcessMessages.
> Zacalo to fungovat  

To je ale jen pul problemu (ta mene zajimava cast   Ta druha pulka je totiz
o tom proc tomu tak je a co presne se tam deje. Napada me, neslo o treba tisk
nejakych vetsich obrazku kde se pouzivala trida TBitmap ? Pokud ano, slo by
zkusit zdali podobny efekt bude mit volani Graphics.FreeMemoryContexts ?

Petr Vones

Odpovedá: Vaclav Krmela

25. 9. 2002 22:59

> From: "Jan Sebelík" <honza@haes.cz>
> > Zavolej "ve vhodnem okamziku" asi tak 3-5 x
> > Aplication.ProcessMessages.
> > Zacalo to fungovat  
>
> From: Petr Vones
> To je ale jen pul problemu (ta mene zajimava cast  
> Ta druha pulka je totiz
> o tom proc tomu tak je a co presne se tam deje.

Samozrejme jsem nad tim badal, ale neuspesne.
Jedine na co jsem prisel bylo, ze cetnost vyskytu
problemu je umerna slozitosti ovladace tiskarny.
Tim myslim pocet DLL ktere ovladac tiskarny potrebuje.
Pripadalo mi to tak, ze ProcessMessages da sanci ovladaci
ovladaci tiskarny, aby se vzpamatoval.

> Napada me, neslo o treba tisk
> nejakych vetsich obrazku kde se pouzivala trida TBitmap ?
> Pokud ano, slo by
> zkusit zdali podobny efekt bude mit volani
> Graphics.FreeMemoryContexts ?

Slo o tisk obrazku. FreeMemoryContexts zkusim a dam vedet.

Vaclav Krmela

Odpovedá: Petr Vones

25. 9. 2002 23:13

From: "Vaclav Krmela" <krmela@ustinadorlici.cz>
> Slo o tisk obrazku. FreeMemoryContexts zkusim a dam vedet.

V tom pripade je hlavne nutne nepouzivat TCanvas.StretchDraw pro tisk na
tiskarnu protoze tato operace je ve Windows nepodporovana a skutecnost ze to
nekdy funguje je zavadejici. Pro tisk je nutno vytvorit DIB a pouzit funkci
StretchDiBits.

INFO: Blitting Between DCs for Different Devices Is Unsupported
http://support.microsoft.com/default.aspx?scid=KB;EN-US;q195830

http://www.efg2.com/Lab/Library/Delphi/Printing/StretchDIBitsDemo.txt

Petr Vones

Odpovedá: Lumir Karas

28. 9. 2002 0:23

Ahoj,
 mimo jine Application.ProcessMessages volane z rychle se opakujici smycky,
take pekne zatezuje CPU protoze si myslim (nevim to 100%), ze vlastne
nasilne donuti windows aby zpracovaly veskere zpravy cekajici na zpracovani.

Lomikar.

Odpovedá: Robert Suska

29. 9. 2002 16:50

Ahoj!

Pouzi v cykle while do aj Sleep(0);

cize

while do
 begin
   Sleep(0);
   Application.ProcessMessage;
  end;

a toto by Ti malo fungovat ok.

S pozdravo Robert Suska



> Ahoj,
> mimo jine Application.ProcessMessages volane z rychle se opakujici
smycky,
> take pekne zatezuje CPU protoze si myslim (nevim to 100%), ze vlastne
> nasilne donuti windows aby zpracovaly veskere zpravy cekajici na
zpracovani.
>
> Lomikar.